// SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
// SPDX-License-Identifier: Mulan PSL v2
package main

import (
	"context"
	"flag"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"

	_ "net/http/pprof"

	_ "code.geniusai.org/notebook-manager/cmd/manager/docs"
	"code.geniusai.org/notebook-manager/pkg/config"
	"code.geniusai.org/notebook-manager/pkg/handler"
	"code.geniusai.org/notebook-manager/pkg/log"
	"code.geniusai.org/notebook-manager/pkg/resource"
	"code.geniusai.org/notebook-manager/pkg/utils/xss"
)

const (
	//ServiceManagerLogID = "notebook-manager"
	CloseTimeout = 5
)

func setupRouter(confData *config.Conf) *gin.Engine {
	resourceManager := resource.NewManager(confData)
	err := resourceManager.Init()
	if err != nil {
		log.Panicf("init resourceManager error: %v", err)
	}

	router := gin.Default()

	// 健康检查
	router.GET("/healthz", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
		})
	})

	// 避免panic
	router.Use(handler.RecoveryInterceptor)
	// xss
	xssMdlwr := &xss.XssMw{}
	router.Use(xssMdlwr.RemoveXss(), log.AuditLogger)

	if confData.SwaggerUI {
		router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
	}

	notebookHandler := handler.NewNotebookHandler(resourceManager, confData)
	pvcHandler := handler.NewPvcHandler(resourceManager)
	monitorHandler := handler.NewMonitorHandler(resourceManager, confData)
	// 路由组：/notebooks/v1
	notebooV1 := router.Group("/notebooks/v1")
	// 增加拦截器
	//httpInterceptor := interceptor.NewHttpInterceptorHandler(resourceManager, confData)
	//notebooV1.Use(interceptor.NewHttpInterceptor(httpInterceptor, confData).Interceptor())

	{
		notebooV1.POST("/users/:userID/notebooks", handler.Wrapper(notebookHandler.Create))
		notebooV1.GET("/users/:userID/notebooks", handler.Wrapper(notebookHandler.List))
		notebooV1.DELETE("/users/:userID/notebooks", handler.Wrapper(notebookHandler.DeleteRecords))
		notebooV1.DELETE("/notebooks/:id", handler.Wrapper(notebookHandler.Delete))
		notebooV1.DELETE("/project/:projectId/notebooks:batch-delete", handler.Wrapper(notebookHandler.DeleteByProjectId))
		notebooV1.PATCH("/notebooks/:id", handler.Wrapper(notebookHandler.Modify))
		notebooV1.PATCH("/notebooks/:id/start", handler.Wrapper(notebookHandler.Start))
		notebooV1.PATCH("/notebooks/:id/stop", handler.Wrapper(notebookHandler.Stop))
		notebooV1.GET("/notebooks/:id/active", handler.Wrapper(notebookHandler.Active))
		notebooV1.GET("/notebooks/:id/logs", handler.Wrapper(notebookHandler.Logs))
		notebooV1.GET("/notebooks", handler.Wrapper(notebookHandler.ListAll))

		notebooV1.GET("/users/:userID/pvcs", handler.Wrapper(pvcHandler.List))
		notebooV1.DELETE("/pvcs/:id", handler.Wrapper(pvcHandler.Delete))

		notebooV1.POST("/notebooks/show-cpu-usage", handler.Wrapper(monitorHandler.ShowCpuUsage))
		notebooV1.POST("/notebooks/show-memory-usage", handler.Wrapper(monitorHandler.ShowMemoryUsage))
		notebooV1.POST("/notebooks/show-vgpu-usage", handler.Wrapper(monitorHandler.ShowVGpuUsage))
		notebooV1.POST("/notebooks/show-ratio-usage", handler.Wrapper(monitorHandler.ShowRatioUsage))
		notebooV1.POST("/notebooks/show-pvc-usage", handler.Wrapper(monitorHandler.ShowPvcUsage))
	}

	return router
}

// @title Notebook Manager API
// @version 1.0
// @description notebook manager
// @description http://10.61.8.182:8080/swagger/index.html
// @termsOfService http://swagger.io/terms/

// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host 10.61.8.182:8080
// @BasePath /notebooks/v1
func main() {
	// 启用内存监控分析
	go func() {
		if err := http.ListenAndServe("localhost:6969", nil); err != nil {
			fmt.Printf("start pprof failed on %s\n", "6969")
			fmt.Printf("start pprof failed by %s\n", err)
		}
	}()

	//// 定义几个变量，用于接收命令行的参数值
	var conf string
	flag.StringVar(&conf, "conf", "/matrix/etc/config/application.yaml", "-conf /application.yaml")
	argPort := flag.Int("port", 8080, "The port to listen to for incoming HTTP requests")
	flag.Parse()
	log.Init()

	confData := config.LoadConf(conf)

	router := setupRouter(confData)
	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", *argPort),
		Handler: router,
	}
	go func() {
		log.Infof("start service, port: %d", *argPort)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Panicf("listen: %v\n", err)
		}
	}()

	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	ctx, cancel := context.WithTimeout(context.Background(), CloseTimeout*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Panicf("Server forced to shutdown: %v", err)
	}
	log.Infof("Server exiting")
}
